/*
 *  Copyright (C) 2011 Jaime Pavlich-Mariscal
 *
 *  This program is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */


package cl.ucn.disc.biblio.refcluster;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class MultiMap<T1, T2> implements Map<T1, Set<T2>> {
	
	Map<T1, Set<T2>> map;

	public MultiMap() {
		map = getMap();
	}
	
	protected Map<T1, Set<T2>> getMap() {
		return new HashMap<T1, Set<T2>>();
	}
	
	@Override
	public String toString() {
		StringBuffer sb = new StringBuffer();
		for (T1 key : keySet()) {
			sb.append(key);
			sb.append(": ");
			sb.append(get(key));
		}
		return sb.toString();
	}
	@Override
	public boolean containsValue(Object value) {
		throw new UnsupportedOperationException();
	}

	@Override
	public Set<Entry<T1, Set<T2>>> entrySet() {
		throw new UnsupportedOperationException();
	}

	@Override
	public Set<T2> put(T1 key, Set<T2> value) {
		throw new UnsupportedOperationException();
	}

	public T2 add(T1 key, T2 value) {
		if (!containsKey(key)) {
			map.put(key, new LinkedHashSet<T2>());
		}
		map.get(key).add(value);
		return value;
	}
	
	public void remove(T1 key, T2 value) {
		if (containsKey(key)) {
			get(key).remove(value);
		}
	}

	@Override
	public void putAll(Map<? extends T1, ? extends Set<T2>> m) {
		throw new UnsupportedOperationException();
	}

	private static final long serialVersionUID = 1L;

	@Override
	public Set<T2> get(Object key) {
		Set<T2> set = map.get(key);
		if (set == null) {
			set = new LinkedHashSet<T2>();
		} 
		return set;
	}
	
	public List<T2> getList(Object key) {
		return new ArrayList<T2>(get(key));
	}
	
	/** Merges all of the elements referenced by key1 and key2. The new set is referenced by key1
	 * @param key1
	 * @param key2
	 * @return True if the merge is successful, false otherwise.
	 */
	public boolean mergeKeys(String key1, String key2) {
		if (containsKey(key1) && containsKey(key2)) {
			Set<T2> set2 = remove(key2);
			get(key1).addAll(set2);
			return true;
		} else {
			return false;
		}
		
	}
	public void clear() {
		map.clear();
	}
	public boolean containsKey(Object key) {
		return map.containsKey(key);
	}
	public boolean equals(Object o) {
		return map.equals(o);
	}
	public int hashCode() {
		return map.hashCode();
	}
	public boolean isEmpty() {
		return map.isEmpty();
	}
	public Set<T1> keySet() {
		return map.keySet();
	}
	public Set<T2> remove(Object key) {
		return map.remove(key);
	}
	public int size() {
		return map.size();
	}
	public Collection<Set<T2>> values() {
		return map.values();
	}

	
}
